package com.daqsoft.service.project;

import com.daqsoft.dao.project.ProjectDao;
import com.daqsoft.dao.project.ProjectUserDao;
import com.daqsoft.data.Message;
import com.daqsoft.data.User;
import com.daqsoft.data.project.*;
import com.daqsoft.dto.StatusEnum;
import com.daqsoft.dto.TaskTypeEnum;
import com.daqsoft.service.NoticeService;
import com.daqsoft.service.system.PDFService;
import com.daqsoft.service.system.UserManageService;
import com.daqsoft.util.DateUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 项目管理服务层
 *
 * @author 周麟东 on 10:19
 */
@Service
public class ProjectService {

    private Logger log = LoggerFactory.getLogger(getClass());

    @Autowired
    private ProjectDao projectDao;
    @Autowired
    private UserManageService userService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private ProjectUserDao projectUserDao;
    @Autowired
    private PDFService pdfService;
    @Autowired
    private ProjectEditionService projectEditionService;
    @Autowired
    private NodeService nodeService;
    @Autowired
    private AttachmentService attachmentService;

    public List<Project> getByPm(User pm) {
        List<Project> projectList = projectDao.findProjectByPm(pm);
        //去除正在变更的 去除已经隐藏的
        return projectList.stream().filter(p -> p.getStatus() != StatusEnum.CHANGING && p.getStatus() != StatusEnum.HIDDEN && p.getStatus() != StatusEnum.HIDDEN_CAN_CHANGE).collect(Collectors.toList());
    }

    public Project save(Project project, int pmUserId) {
        User pm;
        if (pmUserId == -1) {
            pm = project.getCreator();
        } else {
            pm = userService.findOne(pmUserId);
        }
        if (project.getVersion() == 0){
            project.setVersion(1);
        }
        project.setPm(pm);
        return projectDao.save(project);
    }

    public Project save(Project project) {
        return projectDao.save(project);
    }

    public boolean delete(int id) {
        //先删除项目的文件
        List<Attachment> attachments = attachmentService.getAttByProjectId(id);
        if (attachments != null){
            for (Attachment attachment : attachments) {
                attachmentService.delete(attachment);
            }
        }
        projectDao.delete(id);
        return true;
    }

    public Project get(int projectId) {
        return projectDao.findOne(projectId);
    }

  /*  /**
     * 检查所有未开启的项目 , 如果时间到了就开启了
     * 该线程池每1分钟刷新一次 测试时为每10秒刷新一次
     * TODO 这个方法暂时不用 因为已经有专门开启的流程了
     *//*
    @Scheduled(fixedRate = 1000 * 10)
    public void checkProject(){
        Project project = projectDao.getFirstByStatus(StatusEnum.WAIT);
        if (project == null){
            return;
        }
        Date startDate = project.getStartDate();
        long now = System.currentTimeMillis();
        if(startDate.getTime() < now){
            project.setStatus(StatusEnum.PROCESS);
            projectDao.save(project);
            log.info("项目开启成功",project.toMap());
        }
    }*/


    /**
     * 获取当前项目的所有负责人的集合
     *
     * @param project 项目对象
     * @return map集合  key为userId value为用户对象
     */
    public Map<Integer, User> getAllProjectVerifier(Project project) {
        List<Task> taskList = taskService.getByProject(project, true);
        Map<Integer, User> map = new HashMap<>();
        for (Task task : taskList) {
            User user = task.getVerifier();
            if (!map.containsKey(user.getId())) {
                map.put(user.getId(), user);
            }
        }
        return map;
    }

    /**
     * 通过项目获取当前项目的参与者
     *
     * @param project 项目对象
     * @return 返回参与者集合
     */
    public List<ProjectUser> getProjectUserByProject(Project project) {
        return projectUserDao.findByProject(project);
    }


    public List<Project> getByStatus(StatusEnum statusEnum) {
        return projectDao.getByStatus(statusEnum);
    }

    /**
     * 每天晚上3点执行一次 将还没有完成的项目更新
     */
    @Scheduled(cron = "0 0 3 * * ? ")
    public void createPDF() {
        List<Project> projects = projectDao.getByStatus(StatusEnum.PROCESS);
        try {
            for (Project project : projects) {
                pdfService.parseProject(project);
                log.info("项目[{}](id:{})PDF生成成功", project.getProjectName(), project.getId());

            }
        } catch (Exception e) {
            log.error("获取PDF出错",e);
        }
    }

    /**
     * 通过项目获取PDF
     * @param project
     */
    public void createPDF(Project project){
        try {
            pdfService.parseProject(project);
        } catch (Exception e) {
            log.error("获取PDF出错",e);
//            e.printStackTrace();
        }
    }

    /**
     * 获取全部项目
     *
     * @return 项目
     */
    public List<Project> getAll() {
//        return projectDao.findAll().stream().filter(p -> p.getStatus() != StatusEnum.CHANGING && p.getStatus() != StatusEnum.HIDDEN && p.getStatus() != StatusEnum.HIDDEN_CAN_CHANGE ).collect(Collectors.toList());
        return projectDao.findAll();
    }

    /**
     * 获取某个项目的最终版本
     * @param project 要查询的项目
     * @return 最终版本对象
     */
    public Project getLastVersion(Project project){
        ProjectEdition projectEdition = projectEditionService.getByPrevious(project);
        if (projectEdition == null || projectEdition.getCurrent()  == null){
            return project;
        }else {
            return getLastVersion(projectEdition.getCurrent());
        }
    }

    /**
     * 获取最后一个没有隐藏的版本
     * @param project 任意一个项目
     * @return 跟该项目之前有关的最后一个没有隐藏的版本
     */
    public Project getLastUnHiddenVersion(Project project){
        if (project == null){
            return null;
        }
       ProjectEdition projectEdition = projectEditionService.getByCurrent(project);
        if (projectEdition == null){
            return null;
        }else {
            Project prev = projectEdition.getPrevious();
            if (prev.getStatus()!= StatusEnum.HIDDEN && prev.getStatus()!=StatusEnum.HIDDEN_CAN_CHANGE){
                return prev;
            }else {
                return getLastUnHiddenVersion(prev);
            }
        }
    }

    /**
     * 拷贝项目
     *
     * @param previous 原来的项目
     * @return 拷贝后的项目
     */
    public Project copyProject(Project previous) {
        Project current = new Project();
        current.setProjectName(previous.getProjectName());
        current.setDesc(previous.getDesc());
        current.setStartDate(previous.getStartDate());
        current.setEndDate(previous.getEndDate());
        current.setAcceptance(previous.getAcceptance());
        current.setProjectType(previous.getProjectType());
        current.setCheckType(previous.getCheckType());
        current.setContractAmount(previous.getContractAmount());
        current.setTimeLimit(previous.getTimeLimit());
        current.setContract(previous.getContract());
        current.setArea(previous.getArea());
        current.setStatus(StatusEnum.CHANGING);
        current.setProjectNum(previous.getProjectNum());
        current.setCreator(previous.getCreator());
        current.setPm(previous.getPm());
        current.setProjectNum(previous.getProjectNum());
        current.setVersion(previous.getVersion()+1);
        return current;
    }

    /**
     * 删除正在进行变更的项目
     * 如果这个项目不是最新版本的项目是无法被删除的
     * 如果这个项目就是原始项目也是无法被删除的
     *
     * @param project 项目对象
     * @return 删除是否成功
     */
    @Transactional
    public boolean removeChangeProject(Project project) {

        //先检查当前这个项目是不是最新的项目
        ProjectEdition projectEdition = projectEditionService.getByPrevious(project);
        if (projectEdition != null) { //如果不为空 那么说明不是最新版本 老版本是不能删除的
            return false;
        }
        //查看有没有关系 没有关系的 也不能通过这个方法删除
        projectEdition = projectEditionService.getByCurrent(project);
        if (projectEdition == null) {
            return false;
        }
        //将之前的项目设置为可变更状态
        Project previous = projectEdition.getPrevious();
        previous.setStatus(StatusEnum.CAN_CHANGE);
        save(previous);
        //先删除关系
        projectEditionService.remove(projectEdition);
        //再删除项目
        delete(project.getId());
        return true;
    }

    /**
     * 获取用户的所有项目 包括正在变更的和隐藏的
     *
     * @param user 用户
     * @return 项目列表
     */
    public List<Project> getAllByPm(User user) {
        return projectDao.findProjectByPm(user);
    }

    /**
     * 比较两个不同的项目的基础信息
     *
     * @param p1 项目1 对象
     * @param p2 项目2 对象
     * @return 比较的结果
     */
    public Object projectInfoCompar(Project p1, Project p2) {
        List<Map<String, Object>> list = new ArrayList<>();
        Map<String, Object> map = new HashMap<>();
        map.put("field", "项目名称");
        map.put("value", new String[]{p1.getProjectName(), p2.getProjectName()});
        list.add(map);

        map = new HashMap<>();
        map.put("field", "项目编号");
        map.put("value", new String[]{p1.getProjectNum(), p2.getProjectNum()});
        list.add(map);

        map = new HashMap<>();
        map.put("field", "项目开始时间");
        map.put("value", new String[]{DateUtil.INS.parse(p1.getStartDate()), DateUtil.INS.parse(p2.getStartDate())});
        list.add(map);

        map = new HashMap<>();
        map.put("field", "项目结束时间");
        map.put("value", new String[]{DateUtil.INS.parse(p1.getStartDate()), DateUtil.INS.parse(p2.getStartDate())});
        list.add(map);

        map = new HashMap<>();
        map.put("field", "审核类型");
        map.put("value", new int[]{p1.getCheckType(), p2.getCheckType()});
        list.add(map);

        map = new HashMap<>();
        map.put("field", "合同金额(元)");
        map.put("value", new double[]{p1.getContractAmount(), p2.getContractAmount()});
        list.add(map);

        map = new HashMap<>();
        map.put("field", "合同工期(天)");
        map.put("value", new int[]{p1.getTimeLimit(), p2.getTimeLimit()});
        list.add(map);

        map = new HashMap<>();
        map.put("field", "项目说明");
        map.put("value", new String[]{p1.getDesc(), p2.getDesc()});
        list.add(map);

        return list;
    }

    /**
     * 比较两个不同的项目的计划信息
     *
     * @param p1 项目1 对象
     * @param p2 项目2 对象
     * @return 比较的结果
     */
    public List<Map<String, Object>> projectPlanCompar(Project p1, Project p2) {
        //先查出节点
        List<Node> p1Nodes = p1.getNodes();
        List<Node> p2Nodes = p2.getNodes();
        List<Map<String, Object>> maps = new ArrayList<>();
        //融合节点
        boolean isP1Big = p1Nodes.size() >= p2Nodes.size();
        List<Node> bigOne = isP1Big ? p1Nodes : p2Nodes;
        for (Node big : bigOne) {
            Map<String, Object> map = new HashMap<>();
            int index = big.getIndex();
            Node small = isP1Big ? nodeService.getNodeByIndex(p2, index) : nodeService.getNodeByIndex(p1, index); // 通过P1的index来找NODE
            Node node1;
            Node node2;
            if (isP1Big){
                node1 = big;
                node2 = small;
            }else {
                node2 = big;
                node1 = small;
            }

            map.put("id", new int[]{node1 == null ? 0 : big.getId(),node2 == null ? 0 : node2.getId()});
            map.put("name", new String[]{node1 == null ? "" :big.getName(),node2 == null ? "" : node2.getName()});
            map.put("startDate", new String[]{node1 == null ? "" :DateUtil.INS.parse(big.getStartDate()), node2 == null ? "" : DateUtil.INS.parse(node2.getStartDate())});
            map.put("endDate", new String[]{node1 == null ? "" :DateUtil.INS.parse(big.getEndDate()), node2 == null ? "" : DateUtil.INS.parse(node2.getEndDate())});

            //处理节点下的任务
            map.put("children",nodeService.comparNode(node1 , node2));
            map.put("expanded",true);

            maps.add(map);
        }
        return maps;

    }

}
